from abc import ABC, abstractmethod
from typing import Dict, List, Optional
import ccxt
import pandas as pd
from datetime import datetime

class BaseExchange(ABC):
    """交易所基类"""
    
    def __init__(self, api_key: str, api_secret: str):
        self.api_key = api_key
        self.api_secret = api_secret
        self.exchange = None
        
    @abstractmethod
    def initialize(self):
        """初始化交易所连接"""
        pass
        
    @abstractmethod
    def get_balance(self) -> Dict:
        """获取账户余额"""
        pass
        
    @abstractmethod
    def get_ticker(self, symbol: str) -> Dict:
        """获取最新行情"""
        pass
        
    @abstractmethod
    def get_orderbook(self, symbol: str, limit: int = 20) -> Dict:
        """获取订单簿"""
        pass
        
    @abstractmethod
    def get_ohlcv(self, symbol: str, timeframe: str, limit: int = 100) -> pd.DataFrame:
        """获取K线数据"""
        pass
        
    @abstractmethod
    def create_order(self, symbol: str, order_type: str, side: str, 
                    amount: float, price: Optional[float] = None) -> Dict:
        """创建订单"""
        pass
        
    @abstractmethod
    def cancel_order(self, order_id: str, symbol: str) -> bool:
        """取消订单"""
        pass
        
    @abstractmethod
    def get_open_orders(self, symbol: str = None) -> List[Dict]:
        """获取未完成订单"""
        pass
        
    @abstractmethod
    def get_order_status(self, order_id: str, symbol: str) -> Dict:
        """获取订单状态"""
        pass
        
    @abstractmethod
    def get_position(self, symbol: str) -> Dict:
        """获取持仓信息"""
        pass
        
    def format_ohlcv(self, data: List) -> pd.DataFrame:
        """格式化K线数据"""
        df = pd.DataFrame(data, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
        df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
        return df
        
    def handle_error(self, e: Exception):
        """处理错误"""
        error_msg = f"Exchange error: {str(e)}"
        # TODO: 添加日志记录
        print(error_msg)
        return None
